#include "assert.h"

#include "tokenizer.h"

Token Tokenizer::GetToken()
{
	Token token;
	int newPos = 0;
	bool bExist = peekToken(token, newPos);
	assert(bExist);
	position = newPos;
	return token;
}

bool Tokenizer::PeekToken(Token& token) const
{
	int newPos = 0;
	return peekToken(token, newPos);
}

bool Tokenizer::IsEnd() const
{
	Token token;
	return !PeekToken(token);
}

inline static bool is_digit(char symbol)
{
	return symbol >= '0' && symbol <= '9';
}

bool Tokenizer::peekToken(Token& token, int& newPos) const
{
	if (position == inputString.length()) {
		return false;
	}
	switch (inputString[position]) {
	case '+':
		token.Type = Token::TT_BinaryAdd;
		newPos = position + 1;
		break;
	case '-':
		token.Type = Token::TT_BinarySubtract;
		newPos = position + 1;
		break;
	case '*':
		token.Type = Token::TT_Mult;
		newPos = position + 1;
		break;
	case '/':
		token.Type = Token::TT_Div;
		newPos = position + 1;
		break;
	case '(':
		token.Type = Token::TT_OpenBracket;
		newPos = position + 1;
		break;
	case ')':
		token.Type = Token::TT_CloseBracket;
		newPos = position + 1;
		break;
	default:
		{
			size_t offset = 0;
			while (is_digit(inputString[position + offset]) && position + offset < inputString.length()) {
				offset++;
			}
			if (position + offset < inputString.length() && inputString[position + offset] == '.') {
				offset++;
				while (is_digit(inputString[position + offset]) && position + offset < inputString.length()) {
					offset++;
				}
			}
			assert(offset > 0);
			string valueStr = inputString.substr(position, offset);
			double dblval = atof(valueStr.c_str());
			assert(errno == 0);
			token.Type = Token::TT_Number;
			token.Value = dblval;
			newPos = position + offset;
		}
	}
	return true;
}